#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,a,b) for(register int i = (a);i <= (b);++i)
#define per(i,a,b) for(register int i = (a);i >= (b);--i)  
typedef long long ll;
typedef unsigned long long ull;
using std::string;using std::cin;using std::cout;

const int N = 1e5+5;
int n,m,root,p,a[2*N],b[2*N],x,y,z,opt;
int head[2*N],next[2*N],ver[2*N],tot;
int fa[2*N],top[2*N],deep[2*N],son[2*N],size[2*N],id[2*N];

//------------------------------------------------------

inline void link(int x,int y){ver[++tot] = y , next[tot] = head[x] , head[x] = tot;}

inline void dfs1(int now,int father){
    size[now] = 1 , deep[now] = deep[father] + 1 , fa[now] = father;
    for(int i = head[now];i;i = next[i]){
        if(ver[i] == fa[now]) continue;
        dfs1(ver[i],now);
        size[now] += size[ ver[i] ];
        son[now] = size[ son[now] ] > size[ ver[i] ] ? son[now] : ver[i]; // 更新重儿子
    }
    return;
}

inline void dfs2(int now,int toper){
    id[now] = ++id[0] , top[now] = toper , b[id[0]] = a[now];
    if(!son[now]) return; // 没有重儿子即叶子节点
    dfs2(son[now],toper); // 重儿子先走
    for(int i = head[now];i;i = next[i]){
        if(id[ ver[i] ]) continue;
        dfs2(ver[i],ver[i]);
    }
    return;
}

//------------------------------------------------------

int TOT;
struct node{
    int l,r;
    ll sum,tag;
    int dis(){return r-l+1;}
    node * ls, * rs;
}Tree[4*N];

inline node * create(){return &Tree[++TOT];}

inline void pushdown(node * cur){
    cur->ls->sum += cur->tag * cur->ls->dis(), cur->ls->sum %= p;
    cur->ls->tag += cur->tag , cur->ls->tag %= p;
    cur->rs->sum += cur->tag * cur->rs->dis(), cur->rs->sum %= p;
    cur->rs->tag += cur->tag , cur->rs->tag %= p;
    cur->tag = 0;
    return;
}

inline void pushup(node * cur){cur->sum = (cur->ls->sum + cur->rs->sum)%p;}

inline void build(node * cur,int l,int r){
    cur->l = l , cur->r = r , cur->sum = cur->tag = 0;
    if(cur->l == cur->r){cur->sum = b[l];return;}
    int mid = (l+r)>>1;
    cur->ls = create() , cur->rs = create();
    build(cur->ls,l,mid) , build(cur->rs,mid+1,r);
    pushup(cur);
    return;
}

inline void edit(node * cur,int l,int r,int x){
    if(l > cur->r || r < cur->l) return;
    if(l <= cur->l && cur->r <= r){
        cur->sum += x * cur->dis() % p , cur->sum %= p , cur->tag += x;
        return;
    }
    if(cur->l == cur->r) return;
    pushdown(cur);
    if(l <= cur->ls->r) edit(cur->ls,l,r,x);
    if(r >= cur->rs->l) edit(cur->rs,l,r,x);
    pushup(cur);
    return;
}

inline ll query(node * cur,int l,int r){
    if(l > cur->r || r < cur->l) return 0;
    if(l <= cur->l && cur->r <= r) return cur->sum;
    pushdown(cur);
    return (query(cur->ls,l,r) + query(cur->rs,l,r))%p;
}

//------------------------------------------------------

inline void edit_chain(node * cur){
    //把x到y都加上z
    while(top[x] != top[y]){
        if(deep[ top[x] ] < deep[ top[y] ]) std::swap(x,y);
        edit(cur,id[top[x]],id[x],z);
        x = fa[ top[x] ];
    }
    if(id[x] > id[y]) std::swap(x,y);
    edit(cur,id[x],id[y],z);
    return;
}

inline void query_chain(node * cur){
    //查询x到y的和
    ll ans = 0;
    while(top[x] != top[y]){
        if(deep[ top[x] ] < deep[ top[y] ]) std::swap(x,y);
        ans += query(cur,id[top[x]],id[x]) , ans %= p;
        x = fa[top[x]];
    }
    if(id[x] > id[y]) std::swap(x,y);
    ans += query(cur,id[x],id[y]) , ans %= p;
    cout << ans << "\n";
    return;
}

inline void edit_tree(node * cur){
    //给x的子树都加上z
    edit(cur,id[x],id[x]+size[x]-1,z);
    return;
}

inline void query_tree(node * cur){
    //查询x的子树和
    cout << query(cur,id[x],id[x]+size[x]-1) << "\n";
    return;
}

//------------------------------------------------------

inline void check(node * cur){
    rep(i,1,n){
        x = y = i;
        query_chain(cur);
    }
}

//------------------------------------------------------

int main(){
    std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //freopen("in.in", "r", stdin);
    cin >> n >> m >> root >> p;
    rep(i,1,n) cin >> a[i];
    rep(i,1,n-1){
        cin >> x >> y;
        link(x,y) , link(y,x);
    }
    fa[root] = 0 , deep[fa[root]] = 0;
    dfs1(root,0);
    dfs2(root,root);
    node * Root = create();
    build(Root,1,n);
    while(m--){
        cin >> opt;
        if(opt == 1){//链改
            cin >> x >> y >> z;
            z %= p;
            edit_chain(Root);
        } else if(opt == 2){//链查
            cin >> x >> y;
            query_chain(Root);
        } else if(opt == 3){//树改
            cin >> x >> z;
            z %= p;
            edit_tree(Root);
        } else if(opt == 4){//树查
            cin >> x;
            query_tree(Root);
        }
        // cout << "Let's have a check : \n";
        // check(Root);
        // cout << "Over \n";
    }
    return 0;
}